﻿using System;
using System.Collections.Generic;
using System.Web.Mvc;
using MvcContrib.Pagination;
using MvcContrib.Shp.UI.Menu;
using MvcContrib.Shp.UI.Themed.Pager;
using MvcContrib.UI.Grid;
using MvcContrib.UI.Grid.Syntax;

namespace MvcContrib.Shp.UI
{
    /// <summary>
    /// Factory used to namespace MVCContrib UI Components.
    /// </summary>
    public class MvcContribUIComponentFactory
    {
        public MvcContribUIComponentFactory(HtmlHelper htmlHelper)
        {
            if (htmlHelper == null)
                throw new ArgumentNullException("htmlHelper");

            HtmlHelper = htmlHelper;
        }

        public HtmlHelper HtmlHelper { get; set; }

        /// <summary>
        /// Creates a new Grid component.
        /// </summary>
        /// <param name="dataSource">The data source.</param>
        /// <returns></returns>
        public virtual IGrid<T> Grid<T>(IEnumerable<T> dataSource) where T : class
        {
            return new Grid<T>(dataSource, HtmlHelper.ViewContext);
        }

        /// <summary>
        /// Creates a new Grid component.
        /// </summary>
        /// <param name="viewDataKey">The view data key.</param>
        /// <returns></returns>
        public virtual IGrid<T> Grid<T>(string viewDataKey) where T : class
        {
            var dataSource = HtmlHelper.ViewContext.ViewData.Eval(viewDataKey) as IEnumerable<T>;

            if (dataSource == null)
            {
                throw new InvalidOperationException(
                    string.Format("Item in ViewData with key '{0}' is not an IEnumerable of '{1}'.",
                                  viewDataKey,
                                  typeof (T).Name));
            }

            return Grid(dataSource);
        }

        #region Pager Component

        /// <summary>
        /// Creates a new <see cref="MvcContrib.UI.Pager.Pager"/>
        /// </summary>
        /// <param name="viewDataKey">The view data key.</param>
        /// <returns></returns>
        public virtual MvcContrib.UI.Pager.Pager Pager(string viewDataKey)
        {
            return Pager(GetPagination(viewDataKey));
        }

        /// <summary>
        /// Creates a new <see cref="MvcContrib.UI.Pager.Pager"/>
        /// </summary>
        /// <param name="dataSource">The data source.</param>
        /// <returns></returns>
        public virtual MvcContrib.UI.Pager.Pager Pager(IPagination dataSource)
        {
            return new MvcContrib.UI.Pager.Pager(dataSource, HtmlHelper.ViewContext);
        }

        /// <summary>
        /// Creates a new <see cref="Themed.Pager.PagerThemed"/>
        /// </summary>
        /// <param name="viewDataKey">The view data key.</param>
        /// <returns></returns>
        public virtual PagerThemed PagerThemed(string viewDataKey)
        {
            return PagerThemed(GetPagination(viewDataKey));
        }

        /// <summary>
        /// Creates a new <see cref="Themed.Pager.PagerThemed"/>
        /// </summary>
        /// <param name="dataSource">The data source.</param>
        /// <returns></returns>
        public virtual PagerThemed PagerThemed(IPagination dataSource)
        {
            return new PagerThemed(dataSource, HtmlHelper.ViewContext);
        }

        protected virtual IPagination GetPagination(string viewDataKey)
        {
            var dataSource = HtmlHelper.ViewContext.ViewData.Eval(viewDataKey) as IPagination;

            if (dataSource == null)
            {
                throw new InvalidOperationException(
                    string.Format("Item in ViewData with key '{0}' is not an IPagination.", viewDataKey));
            }

            return dataSource;
        }

        #endregion #region Pager Component

        #region Menu Component

        public virtual Menu.Menu Menu()
        {
            return new Menu.Menu(HtmlHelper.ViewContext);
        }

        public virtual Menu.Menu Menu(Action<MenuSettings> settings)
        {
            var menu = new Menu.Menu(HtmlHelper.ViewContext);
            settings(menu.Settings);
            return menu;
        }

        #endregion Menu Component
    }
}